﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Campus {
    class GarrisonAbility : Ability {
        private List<Unit> m_garrisonedUnits;
        public List<Unit> GarrisonedUnits {
            get { return m_garrisonedUnits; }
        }

        private int m_range;

        public delegate bool GarrisonCheck(Unit unit);
        private GarrisonCheck m_canGarrison;  

        public GarrisonAbility(AbilityMenuIcon icon, BaseEntity owner, int range, GarrisonCheck canGarrisonMethod)
            : base(icon, owner, null, TargetTypes.Unit) {
            m_range = range;
            m_canGarrison = canGarrisonMethod;
            m_garrisonedUnits = new List<Unit>();
            MenuDelegate = delegate(string option) {
                Campus.cursor.ActionState = CursorActionState.move;
                Campus.cursor.ClickMethod = delegate(Vector2 gamePoint) {
                    Target = Cursor.GetBaseEntityAtPoint(gamePoint, Owner.PlayerOwner);
                    Owner.SetCurrentAbility(this);
                    Campus.cursor.ClickMethod = null;
                    Campus.cursor.ActionState = CursorActionState.idle;
                };
            };
        }
        public GarrisonAbility(GarrisonAbility copySource)
            : base(copySource) {
            m_range = copySource.m_range;
            m_canGarrison = copySource.m_canGarrison;
            m_garrisonedUnits = new List<Unit>(copySource.m_garrisonedUnits);
            MenuDelegate = delegate(string option) {
                Campus.cursor.ActionState = CursorActionState.move;
                Campus.cursor.ClickMethod = delegate(Vector2 gamePoint) {
                    Target = Cursor.GetBaseEntityAtPoint(gamePoint, Owner.PlayerOwner);
                    Owner.SetCurrentAbility(this);
                    Campus.cursor.ClickMethod = null;
                    Campus.cursor.ActionState = CursorActionState.idle;
                };
            };
        }
        public override void Update(GameTime gameTime, bool checkInput, bool updateBoundingBox) {
            if (Target is Unit && Target != null) {
                Unit unit = (Unit)Target;
                if (m_canGarrison(unit)) {
                    double distanceX = unit.Position.X - Owner.Position.X;
                    double distanceY = unit.Position.Y - Owner.Position.Y;
                    double distanceToTarget = Math.Sqrt(distanceX * distanceX + distanceY * distanceY);
                    if (m_range < distanceToTarget) {
                        if (0 < unit.AbilityQueue.Count) {
                            if (!(unit.AbilityQueue.Peek() is MoveAbility)) {
                                unit.Stop();
                                MoveAbility move = (MoveAbility)unit.GetMoveAbility().Clone();
                                move.FinalDestination = Owner.Position;
                                move.StopDelegate = delegate() {
                                    double distX = unit.Position.X - Owner.Position.X;
                                    double distY = unit.Position.Y - Owner.Position.Y;
                                    double distToTarget = Math.Sqrt(distX * distX + distY * distY);
                                    return distToTarget < m_range;
                                };
                                unit.SetCurrentAbility(move);
                            }
                        } else {
                            unit.Stop();
                            MoveAbility move = (MoveAbility)unit.GetMoveAbility().Clone();
                            move.FinalDestination = Owner.Position;
                            move.StopDelegate = delegate() {
                                double distX = unit.Position.X - Owner.Position.X;
                                double distY = unit.Position.Y - Owner.Position.Y;
                                double distToTarget = Math.Sqrt(distX * distX + distY * distY);
                                return distToTarget < m_range;
                            };
                            unit.SetCurrentAbility(move);
                        }
                    } else {
                        //the unit can be garrisoned in this building
                        ((GarrisonAbility)Owner.Abilities["Garrison"]).GarrisonedUnits.Add(unit);
                        unit.IsVisible = false;
                        unit.IsUsable = false;
                        IsAbilityDone = true;
                    }
                }
            } else {
                this.IsAbilityDone = true;
            }
        }
        public override Ability Clone() {
            return new GarrisonAbility(this);
        }
    }
}
